/*
 *   Copyright (c) 2010-2022, SIUFUNG
 */
package net.siufung.market.base.permit.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.siufung.core.exception.BizServiceException;
import net.siufung.core.model.enums.DeletedEnum;
import net.siufung.core.utils.StringPool;
import net.siufung.market.base.permit.enums.AccessStates;
import net.siufung.market.base.permit.enums.BusinessTypes;
import net.siufung.market.base.permit.enums.PermitTypes;
import net.siufung.market.base.permit.mapper.IMenuMapper;
import net.siufung.market.base.permit.mapper.entity.Menu;
import net.siufung.market.base.permit.mapper.entity.Permit;
import net.siufung.market.base.permit.service.IMenuService;
import net.siufung.market.base.permit.service.IPermitService;
import net.siufung.mybatis.base.BaseServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 系统菜单表 数据服务实现
 *
 * @author 陈建峰
 * @since 2022-07-05 22:19:50
 */
@Slf4j
@AllArgsConstructor
@Service(value = "menuService")
@Transactional(rollbackFor = Exception.class)
public class MenuServiceImpl extends BaseServiceImpl<IMenuMapper, Menu> implements IMenuService {

    private final IPermitService permitService;

    @Override
    public boolean removeById(Serializable id) {
        if(super.removeById(id)){
            permitService.remove(new LambdaQueryWrapper<Permit>().eq(Permit::getMenuId, id));
            //是否要删除角色权限中的权限信息
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    @Override
    public boolean save(Menu menu) {
        if (Objects.isNull(menu.getParentId())
                || Integer.valueOf(StringPool.ZERO).equals(menu.getParentId())) {
            menu.setLevel(Integer.parseInt(StringPool.ZERO));
            menu.setFullPath(StringPool.SLASH);
        } else {
            Menu parentMenu = getBaseMapper().selectById(menu.getParentId());
            menu.setLevel(
                    ObjectUtil.defaultIfNull(parentMenu.getLevel(), Integer.parseInt(StringPool.ZERO))
                            + Integer.parseInt(StringPool.ONE));
            menu.setParentName(parentMenu.getMenuName());
            menu.setFullPath(parentMenu.getFullPath() + StringPool.SLASH + menu.getRouter());
            if(Integer.valueOf(StringPool.ONE).equals(menu.getParentId())){
                menu.setFullPath(StringPool.SLASH + menu.getRouter());
            }
        }
        if(Strings.isNullOrEmpty(menu.getMenuCode())){
            menu.setMenuCode(getRandomMenuCode(8));
        }
        if(Objects.isNull(menu.getExternalState())){
            menu.setExternalState(false);
        }
        if(Strings.isNullOrEmpty(menu.getBusinessType())){
            menu.setBusinessType(BusinessTypes.ALL.getValue());
        }
        menu.setSign(StringPool.DASH);
        return super.save(menu);
    }


    @Override
    public Boolean save(Menu menu, List<Permit> permitList) {
        if (AccessStates.NOT.getValue().equals(menu.getAccessState())) {
            throw new BizServiceException("菜单类型为不可执行，请选用save(T)实现功能");
        }
        if (this.save(menu)) {
            List<String> allPermitCodeList = permitService.getBaseMapper().selectList(Wrappers.query())
                    .stream().map(Permit::getPermitCode).collect(Collectors.toList());
            String permitCode;
            int sequence = 0;
            Permit permit = new Permit();
            permit.setPermitName(menu.getMenuName());
            permitCode = permitService.getRandomPermitCode(8, allPermitCodeList);
            allPermitCodeList.add(permitCode);
            permit.setPermitCode(permitCode);
            permit.setPermitType(PermitTypes.LINK.getValue());
            permit.setBusinessType(menu.getBusinessType());
            permit.setMenuId(menu.getId());
            permit.setParentId(null);
            permit.setText(menu.getMenuName());
            permit.setSign(StringPool.DASH);
            permit.setSequence(sequence);
            permitService.save(permit);
            if(permitList.size() > 0){
                for (Permit childPermit : permitList) {
                    childPermit.setPermitName(StrUtil.concat(false, permit.getText(),
                            StringPool.DASH, childPermit.getText()));
                    permitCode = permitService.getRandomPermitCode(8, allPermitCodeList);
                    allPermitCodeList.add(permitCode);
                    childPermit.setPermitCode(permitCode);
                    childPermit.setParentId(permit.getId());
                    childPermit.setPermitType(PermitTypes.BUTTON.getValue());
                    childPermit.setMenuId(menu.getId());
                    childPermit.setBusinessType(menu.getBusinessType());
                    sequence++;
                    childPermit.setSequence(sequence);
                }
                return permitService.saveBatch(permitList);
            }
        }
        return Boolean.FALSE;
    }

    @Override
    public Boolean updateById(Menu menu, List<Permit> permitList) {
        if(super.updateById(menu)){
            if(CollectionUtils.isEmpty(permitList)){
              permitService.remove(new LambdaQueryWrapper<Permit>()
                      .eq(Permit::getMenuId, menu.getId())
                      .eq(Permit::getPermitType, PermitTypes.BUTTON.getValue()));
            } else {
                permitService.updateBatchByMenuId(menu.getId(), permitList);
            }
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    @Override
    public boolean updateStatusById(Serializable id, DeletedEnum deletedEnum) {
        if(super.update(
                new LambdaUpdateWrapper<Menu>()
                        .eq(Menu::getId, id)
                        .set(Menu::getDeleted, deletedEnum.getValue()))){
            // 找到下面所有的菜单
            List<Menu> menuList = Lists.newArrayList();
            List<Menu> allMenuList = getBaseMapper().selectList(Wrappers.query());
            getBaseMapper().getChildMenuList(menuList, id, allMenuList);
            if(!CollectionUtils.isEmpty(menuList)){
                List<Integer> menuIdList = menuList.stream()
                        .map(Menu::getId).collect(Collectors.toList());
                log.info(JSON.toJSONString(menuIdList));
                super.update(
                        new LambdaUpdateWrapper<Menu>()
                                .in(Menu::getId, menuIdList)
                                .set(Menu::getDeleted, deletedEnum.getValue()));
            }
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 获得随机菜单编码
     * @param length 随机码长度
     * @return String
     */
    private String getRandomMenuCode(int length){
        String menuCode = RandomUtil.randomString(length);
        if(getBaseMapper().selectCount(
                new LambdaQueryWrapper<Menu>().eq(Menu::getMenuCode, menuCode)) > 0){
            menuCode = getRandomMenuCode(length);
        }
        return menuCode;
    }



}